/**
 * This file is released under the GNU General Public License.
 * Refer to the COPYING file distributed with this package.
 *
 * Copyright (c) 2008-2009 WURFL-Pro srl
 */
package net.sourceforge.wurfl.core.handlers.matchers;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import net.sourceforge.wurfl.core.Constants;
import net.sourceforge.wurfl.core.handlers.classifiers.FilteredDevices;
import net.sourceforge.wurfl.core.request.WURFLRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * The {@link Matcher} chain-of-responsibility.
 * 
 * <p>
 * This class implements the chain-of-responsibility pattern for the user-agent
 * {@link Matcher}. It is best practice the latest matcher can handle
 * everything and at least must returns <code>generic</code>
 * </p>
 * 
 * @author WURFL-PRO SRL, Rome, Italy
 * @version $Id: MatcherChain.java 1045 2009-03-09 15:52:53Z filippo.deluca $
 */
public class MatcherChain {

	/** The {@link List} of {@link Matcher}. */
	private final List matchers = new ArrayList();

	/** Log */
	private static final Log log = LogFactory.getLog(MatcherChain.class);

	/**
	 * Add a matcher to the chain.
	 * 
	 * @param matcher
	 *            The {@link Matcher} to add.
	 */
	public void add(Matcher matcher) {
		matchers.add(matcher);
	}

	/**
	 * Return the list containing the user-agent matchers.
	 * 
	 * @return A {@link List} of {@link Matcher}s.
	 */
	public List getMatchers() {
		return Collections.unmodifiableList(matchers);
	}

	/**
	 * Perform matching across {@link Matcher} chains.
	 * 
	 * @param request
	 *            The {@link WURFLRequest} to match.
	 * @return The matched device identifier.
	 */
	public String match(WURFLRequest request, FilteredDevices filteredDevices) {

		for (Iterator iterator = matchers.iterator(); iterator.hasNext();) {

			Matcher matcher = (Matcher) iterator.next();

			if (matcher.canHandle(request)) {

				if (log.isDebugEnabled()) {
					log.debug("Matcher: " + matcher + " handle request: "
							+ request);
				}

				String matchedDeviceId = matcher.match(request, filteredDevices);
				
				if (log.isDebugEnabled()) {
					log.debug("Request: " + request + " match device: " + matchedDeviceId);
				}
				
				return matchedDeviceId;
			
			} // end if matcher.canHandle(request)

		}// end for
			

		// No matcher found to match the request
		if (log.isWarnEnabled()) {
			log.warn("No any matcher can handle the request: " + request
					+ ", returning generic device.");
		}

		return Constants.GENERIC;
	}

}
